#ifndef CSE168_SCENE_H_INCLUDED
#define CSE168_SCENE_H_INCLUDED

#include "Miro.h"
#include "Object.h"
#include "PointLight.h"
#include "AreaLight.h"
#include "BVH.h"
#include "EnvMap.h"
#include "Ray.h"


class Camera;
class Image;
class HdrImage;


class Scene
{
public:
	// not sure why these weren't here before - hopefully i'm not missing some important point
	Scene();
	virtual ~Scene();

    void addObject(Object* pObj)        {m_objects.push_back(pObj);}
    const Objects* objects() const      {return &m_objects;}

    void addLight(PointLight* pObj)     {m_lights.push_back(pObj);}
    const Lights* lights() const        {return &m_lights;}

	void addAreaLight(AreaLight* pObj)	{m_areaLights.push_back(pObj);}
    const AreaLights* areaLights() const    {return &m_areaLights;}
	

    void preCalc();
    void openGL(Camera *cam);
	
    void raintraceImage(Camera *cam, HdrImage *img); // render rainbows!
    void raytraceImage(Camera *cam, HdrImage *img);
	void pathtraceImage(Camera *cam, HdrImage *img);
	void metropolisImage(Camera *camp, HdrImage *img);
	void appmImage(Camera *cam, HdrImage *img);

    bool trace(HitInfo& minHit, const Ray& ray,
               float tMin = 0.0f, float tMax = MIRO_TMAX) const;

	void setEnvMap(EnvMap *pEnvMap) 
	{ 
		if (m_pEnvMap) 
			delete m_pEnvMap; 
		m_pEnvMap = pEnvMap; 
	}
	Vector3 getMapValue(Vector3 &dir) const { return m_pEnvMap->getValue(dir); }

	// from Toshiya's PPM code
	void build_hash_grid(const int w, const int h);
	inline unsigned int hash(const int ix, const int iy, const int iz) const
	{
		return (unsigned int) ((ix * 73856093) ^ (iy * 19349663) ^ (iz * 83492791)) % g_num_hash;
	}

protected:
    Objects m_objects;
    BVH *m_pBvh;
    Lights m_lights;
	AreaLights m_areaLights;
	EnvMap *m_pEnvMap;
};

extern Scene * g_scene;


class Stats
{
public:
	Stats()
	{
		reset();
	}
	void reset()
	{
		m_totalRays = 0;
		m_totalTriangleIntersections = 0;
		m_totalBBoxIntersections = 0;
	}
	unsigned long long m_totalRays;
	unsigned long long m_totalTriangleIntersections;
	unsigned long long m_totalBBoxIntersections;
};

extern Stats g_stats;

#endif // CSE168_SCENE_H_INCLUDED
